package agents;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import com.myprofile.profile.MuseumItem;
import com.myprofile.profile.ObjectFactory;
import com.myprofile.profile.ProfileType;

public class TourGenerator {
	
	private static List<MuseumItem> items;
	private static Random rnd;
	
	public static void generateTour() {
		
		rnd = new Random();
		
		ArrayList<String> interests1 = new ArrayList<String>(); // greedy
		ArrayList<String> interests2 = new ArrayList<String>(); // normal

		// ADD INTERESTS
		interests1.add("electrical engineering");
		interests1.add("art");
		interests1.add("mathematics");

		interests2.add("astronomy");
		interests2.add("fine arts");

		// PERSONALIZED ITEMS
		ArrayList<MuseumItem> personalizedItems1 = personalizedItems(interests1);
		ArrayList<MuseumItem> personalizedItems2 = personalizedItems(interests2);

		// INTERESTING ITEMS
		ArrayList<MuseumItem> interestingItems1 = interestingItems(interests1);
		ArrayList<MuseumItem> interestingItems2 = interestingItems(interests2);

		// RANDOM ITEMS
		ArrayList<MuseumItem> randomItems1 = randomItems();
		ArrayList<MuseumItem> randomItems2 = randomItems();

		// Print tours
		printTour("GreedyT3", personalizedItems1);
		printTour("GreedyT2", interestingItems1);
		printTour("GreedyT1", randomItems1);
		printTour("NormalT3", personalizedItems2);
		printTour("NormalT2", interestingItems2);
		printTour("NormalT1", randomItems2);
		
		
		// Make tours
		makeTour("GreedyT3", personalizedItems1);
		makeTour("GreedyT2", interestingItems1);
		makeTour("GreedyT1", randomItems1);
		makeTour("NormalT3", personalizedItems2);
		makeTour("NormalT2", interestingItems2);
		makeTour("NormalT1", randomItems2);
		
	}
	
	private static void printTour(String tourName, ArrayList<MuseumItem> tourItems) {
		System.out.println("Length of " + tourName + ": " + tourItems.size());
		for(MuseumItem mi : tourItems) {
			System.out.println(tourName + "= " + mi.getName() + " : " + mi.getSubject());
		}
	}
	
	private static ArrayList<MuseumItem> personalizedItems(ArrayList<String> interests) {
		
		ArrayList<MuseumItem> chosenItems = new ArrayList<MuseumItem>();
		int divisionPoint = 15/interests.size()+1;
		
		for (int i = 0; i < items.size(); i++) {

			if (chosenItems.size() >= 15)
				break;

			MuseumItem item = items.get(i);
			
			boolean interestingItem = false;
			
			for (String interest : interests) {
				
				System.out.println("Checking item " + item.getName() +  " for interest tag: " + interest);

				// Check how many items we've already chosen for this interest
				int amountOfChosenItems = 0;
				
				for(MuseumItem chosenItem : chosenItems) {
						if(isInteresting(chosenItem.getSubject(), interest)) {
							amountOfChosenItems++;
						}
				}
				boolean fullOnInterest = false;
				
				// See if we have more than this interest in interests
				// If we do, see if we really should be adding more items with this interest
				if(amountOfChosenItems >= divisionPoint) {
					System.out.println("Chosen items for the interest: " + interest + ": " + amountOfChosenItems);
					fullOnInterest = true;
				}
				
				if(!fullOnInterest) {
					if(isInteresting(item.getSubject(), interest)) {
						interestingItem = true;
					}
				}
			}
			
			if(interestingItem) {
				System.out.println("Found an interesting item: " + item.getSubject());
				chosenItems.add(item);
			}
		}

		for (MuseumItem item : chosenItems)
			items.remove(item);

		while (chosenItems.size() < 15) {
			chosenItems.add(items.remove(rnd.nextInt(items.size())));
		}
		return chosenItems;
	}
	
	private static boolean isInteresting(String subjects, String interest) {
		
		StringTokenizer subjectTokenizer = new StringTokenizer(subjects, ",");
		
		while(subjectTokenizer.hasMoreElements()) {
			String subject = (String) subjectTokenizer.nextElement();
			subject = subject.replaceAll(" ", "");
			interest = interest.replaceAll(" ", "");
			if(subject.equals(interest))
				return true;
			}
		
		return false;
	}
	
	private static ArrayList<MuseumItem> interestingItems(ArrayList<String> interests) {

		ArrayList<MuseumItem> chosenItems = new ArrayList<MuseumItem>();
		
		for (int i = 0; i < items.size(); i++) {

			if (chosenItems.size() >= 15)
				break;

			MuseumItem item = items.get(i);

			for (String interest : interests) {
				if (item.getSubject().contains(interest)) {
					chosenItems.add(item);
					break;
				}
			}
		}

		for (MuseumItem item : chosenItems)
			items.remove(item);

		while (chosenItems.size() < 15) {
			chosenItems.add(items.remove(rnd.nextInt(items.size())));
		}
		
		return chosenItems;
	}
	
	private static ArrayList<MuseumItem> randomItems() {
		
		ArrayList<MuseumItem> randomItems = new ArrayList<MuseumItem>();
		
		while (randomItems.size() < 15) {
			randomItems.add(items.remove(rnd.nextInt(items.size())));
		}
		
		return randomItems;
	}
	
	private static void makeTour(String tourName, ArrayList<MuseumItem> tourItems) {
		
		ObjectFactory factory=new ObjectFactory();
		ProfileType profile = factory.createProfileType();
		
		// add the initialized museum items into a collection of visited itmes
		ProfileType.VisitedItems visitedItems = factory
						.createProfileTypeVisitedItems();
		
		for(MuseumItem item : tourItems) {
			MuseumItem it = factory.createMuseumItem();
			it.setId(item.getId());
			it.setName(item.getName());
			it.setSubject(item.getSubject()); // TODO Remove this
			visitedItems.getVisitedItem().add(it);
		}
		
		// add collection of visited items into profile
		profile.setVisitedItems(visitedItems);
		
		// dump profile into an XML file
		JAXBContext jc;
		Marshaller marshaller;
		
		try {
		jc = JAXBContext.newInstance("com.myprofile.profile");
		marshaller = jc.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
		String outputFileName = tourName + ".xml";
		marshaller.marshal(profile, new FileOutputStream(outputFileName));
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
